-- SkyBattle
-- create by panyl
-- 空战模板，负责天空之城战斗的流程播放

-- 类声明
SkyBattle = class("SkyBattle");
function SkyBattle.create(attackerInfo, defenserInfo, result, record, bonus)
    return SkyBattle.new(attackerInfo, defenserInfo, result, record, bonus);
end

--构造函数
function SkyBattle:ctor(attackerInfo, defenserInfo, result, record, bonus)
    self.round = 1;  -- 从1回合开始
    self.step  = 1;  -- 从第一个节点开始播放

    -- 战斗员创建
    local info;
    info = table.deepcopy(attackerInfo);
    info["owner"] = self;
    self.attacker = SkyFighter.new(info, SKY_CITY_ATTACKER);

    info = table.deepcopy(defenserInfo);
    info["owner"] = self;
    self.defenser = SkyFighter.new(info, SKY_CITY_DEFENSER);

    -- 刷新一下战斗对象的属性
    SkyPropM.refreshFightersProp(self.attacker, self.defenser);

    -- 如果防守方继承了上一次的剩余血量，那么调整下防守方的血量
    if defenserInfo["left_hp"] then
        self.defenser.dbase:set("hp", defenserInfo["left_hp"]);
    end

    -- 创建播放序列控制器
    self.sequenceList = SkySequenceList.create(self.attacker, self.defenser);

    -- 保存结果
    self.result = result;

    -- 奖励
    self.bonus = bonus;

    -- 记录（录像）
    self.record = record;
end

-- 回合
function SkyBattle:getRound()
    return self.round;
end

-- 奖励
function SkyBattle:doBonus()
    if not self.bonus then
        return false;
    end

    -- 奖励
    local bonus = self.bonus;
    self.bonus = nil;

    -- 抛出奖励事件
    EventMgr.fire(event.SKY_COMBAT_END, {["bonus"] = bonus, });

    -- 执行奖励
    SkyExploreM.doBonus(bonus);

    return true;
end

-- 判断是否还有为解析的行为
function SkyBattle:checkNextAction()
    local action = self.record[self.step];

    -- 没有行动了，说明已经打完了
    if not action then
        return false;
    else
        return true;
    end
end

-- 行动
function SkyBattle:nextAction()
    local action = self.record[self.step];

    -- 没有行动了，说明已经打完了
    if not action then
        return self:endCombat();
    end

    local order     = { self.attacker, self.defenser, };
    local round     = action[1];
    local at        = action[2] + 1;    -- 服务器的位置是0、1，客户端需要+1
    local source    = order[at];       -- 这个阶段主动攻击方
    local target    = order[SKY_CITY_ATTACKER + SKY_CITY_DEFENSER - at]    -- 这个阶段防守方
    local skillId   = action[3];
    local value     = action[4] or {};

    self.step = self.step + 1;

    if self.round ~= round then
        self.round = round;
        -- 回合变化了，删除过期的skyProp
        SkyPropM.clearRoundProp(self.attacker, round);
        SkyPropM.clearRoundProp(self.defenser, round);
    end

    local result = {};
    if skillId == "prop_trigger" then
        -- 这个行动是属性触发
        trace("SkyBattle", "第 %d 回合：属性触发", round);
        SkyCombatM.roundPropApply(self.attacker, self.defenser, value);
    elseif skillId == "refresh_monster" then
        --
    elseif skillId == "refresh_defenser" then
        --
    elseif skillId == "revive" then
        --
    else
        trace("SkyBattle", "第 %d 回合：%s 释放技能(%d)攻击 %s", round, source:getName(), skillId, target:getName());
        result = SkyCombatM.skillAttack(source, target, skillId, value, round);
    end

    -- 如果已经主动停止播放了，那么直接继续解析行动
    if self.isPositiveEnd then
        return self:nextAction();
    end

    if self.isNextWave then
        return;
    end

    -- 播放序列相关处理

    -- 获取攻击方、防守方的播放序列
    local sourceSequence    = self.sequenceList:getSequenceByFighter(source);
    local targetSequence    = self.sequenceList:getSequenceByFighter(target);
    local skillConfig       = SkyShipSkillM.query(skillId);
    local delay             = 3;        -- 总体消耗时间
    local setup             = 1;        -- 前摇时间

    if type(skillId) == "number" and skillId >= 0 then
        delay = skillConfig.delay;
        setup = skillConfig.setup;
    end

    -- 浮岛上的怪物普通攻击
    if skillId == 0 and type(source.dbase:query("island_type")) == "string" then
        delay = 1;
        setup = 0.5;
    end

    -- 攻击方的播放序列处理

    if skillId == "prop_trigger" then
        -- 如果有属性触发了，那么插入属性触发行为
        local attackerProp = value[SKY_CITY_ATTACKER - 1] or {};
        local defenserProp = value[SKY_CITY_DEFENSER - 1] or {};
        local attackerSequence    = self.sequenceList:getSequenceByFighter(self.attacker);
        local defenserSequence    = self.sequenceList:getSequenceByFighter(self.defenser);

        if type(attackerProp) == "table" and #attackerProp > 0 then
            attackerSequence:addPropEffect(self.attacker, attackerProp);
        end
        if type(defenserProp) == "table" and #defenserProp > 0 then
            defenserSequence:addPropEffect(self.defenser, defenserProp);
        end

        -- 往没有触发或者触发比较少的队列加入等待行为拉平时间
        local maxNum = math.max(#attackerProp, #defenserProp);
        if #attackerProp < maxNum then
            attackerSequence:delay(maxNum - #attackerProp);
        end
        if #defenserProp < maxNum then
            defenserSequence:delay(maxNum - #defenserProp);
        end

        -- 播放
        self.sequenceList:play();

        -- 抛出行为事件
        EventMgr.fire(event.SKY_COMBAT_ACTION, { ["action"] = action });
        return true;
    elseif skillId == "refresh_monster" then
        -- 玩家为攻击方等待，怪物方就刷新为新的波数
        local attackerSequence    = self.sequenceList:getSequenceByFighter(self.attacker);
        local defenserSequence    = self.sequenceList:getSequenceByFighter(self.defenser);

        --
        attackerSequence:delay(3.5);

        -- value是赢的次数客户端，取出当前波数
        -- 旧的怪物需要干掉，这边先生成新的
        local whirlpoolCombat = self.defenser.dbase:query("whirlpool_combat");
        local exploreLevel = self.defenser.dbase:query("explore_level");
        local id = whirlpoolCombat[value + 1];
        local defenserInfo = SkyWhirlpoolM.getDefenserInfo(id, exploreLevel, whirlpoolCombat);

        local info = table.deepcopy(defenserInfo);
        info["owner"] = self;
        self.defenser = SkyFighter.new(info, SKY_CITY_DEFENSER);

        -- 这边防守方改了
        defenserSequence:updateFighter(self.defenser);

        defenserSequence:addRefreshMonster(self.defenser);

        -- 播放
        self.sequenceList:play();

        -- 抛出行为事件
        EventMgr.fire(event.SKY_COMBAT_ACTION, { ["action"] = action });
        return true;
    elseif skillId == "refresh_defenser" then
        -- 玩家为攻击方等待，怪物方就刷新为新的波数
        local attackerSequence    = self.sequenceList:getSequenceByFighter(self.attacker);
        local defenserSequence    = self.sequenceList:getSequenceByFighter(self.defenser);

        --
        attackerSequence:delay(3.5);

        -- value是赢的次数客户端，取出当前波数
        -- 旧的怪物需要干掉，这边先生成新的
        local defenser_list = self.extraData;
        local defenserInfo = defenser_list[value];

        local info = table.deepcopy(defenserInfo);
        info["owner"] = self;
        self.defenser = SkyFighter.new(info, SKY_CITY_DEFENSER);

        -- 这边防守方改了
        defenserSequence:updateFighter(self.defenser);

        defenserSequence:addRefreshMonster(self.defenser);

        -- 播放
        self.sequenceList:play();

        -- 抛出行为事件
        EventMgr.fire(event.SKY_COMBAT_ACTION, { ["action"] = action });
        return true;
    elseif skillId == "revive" then
        -- 复活
        source:revive(value);

        sourceSequence:cure(source, target, skillId, {["cure"] = value});
        targetSequence:delay(1);

        -- 播放
        self.sequenceList:play();

        -- 抛出行为事件
        EventMgr.fire(event.SKY_COMBAT_ACTION, { ["action"] = action });
        return true;
    end

    -- 往攻击的播放序列加入 攻击动作
    sourceSequence:attack(source, target, skillId, result);

    -- 如果技能的释放结果对自己产生了回血，那么播放治疗效果
    if result["cure"] > 0 then
        -- 治疗效果
        sourceSequence:cure(source, target, skillId, result);
    end

    -- 攻击后是否对自己有效果
    local casterEffect = skillConfig["caster_effect"];
    if type(casterEffect) == "string" and string.len(casterEffect) > 0 then
        -- 攻击技能对自己有影响，那么播放效果

        -- 附加状态效果
        sourceSequence:addBuff(source, skillId, casterEffect);
    end

    -- 延迟到攻击阶段结束
    sourceSequence:delay(delay - setup);

    -- 往防守方的播放序列加入 攻击方的攻击动作前摇时间等待
    targetSequence:delay(setup);

    if result["damage"] > 0 then
        -- 往防守方的播放序列中加入 受创动作
        targetSequence:receiveDamage(target, skillId, result["damage"], result);
    end

    -- 受创方的附件效果
    local damagedEffect = skillConfig["damaged_effect"];
    if type(damagedEffect) == "string" and string.len(damagedEffect) > 0 then
        -- 附加负面状态效果
        targetSequence:addDebuff(target, skillId, damagedEffect);
    end

    -- 延迟到攻击阶段结束
    targetSequence:delay(delay - setup);

    -- 其他的播放序列就直接等待就好了
    for _, sequence in ipairs(self.sequenceList:getSequenceList()) do
        if sequence.fighter ~= self.attacker and sequence.fighter ~= self.defenser then
            sequence:delay(delay);
        end
    end

    -- 播放
    self.sequenceList:play();

    -- 抛出行为事件
    EventMgr.fire(event.SKY_COMBAT_ACTION, { ["action"] = action });

    return true;
end

-- 结束战斗
function SkyBattle:endCombat()
    -- 抛出战斗结束事件
    EventMgr.fire(event.SKY_COMBAT_END, {["battle"] = self, ["bonus"] = self.bonus});

    -- 执行奖励操作
    self:doBonus();
end

-- 尝试结束战斗（这里用于UI层主动停止播放）
function SkyBattle:tryToEnd()
    self.isPositiveEnd = true;
end

-- 检查剩下action还有没刷新怪物的行为
function SkyBattle:checkRefreshMonster()
    local step = self.step;

    for index = step, #self.record do
        if type(self.record[index]) == "table" and self.record[index][3] == "refresh_monster" then
            return true;
        end
    end

    return false;
end

-- 调到下一波怪
function SkyBattle:nextWaveMonster()
    local step = self.step;

    local action;

    for index = step, #self.record do
        action = self.record[index];
        if type(action) == "table" and action[3] == "refresh_monster" then
            self.isNextWave = false;
            break;
        end

        self.isNextWave = true;
        self:nextAction();
    end

    -- 先将当前的清空掉
    self.sequenceList:resetActionSequence();
end
